<script lang="ts" setup>
import { i18n } from "@/locales";
import type { CommandMenuItemType } from "@/types";
import scrollIntoView from "scroll-into-view-if-needed";
import { ref, watch, type PropType } from "vue";

const props = defineProps({
  items: {
    type: Array as PropType<CommandMenuItemType[]>,
    required: true,
  },

  command: {
    type: Function as PropType<(item: CommandMenuItemType) => void>,
    required: true,
  },
});

const selectedIndex = ref(0);

watch(
  () => props.items,
  () => {
    selectedIndex.value = 0;
  }
);

function onKeyDown({ event }: { event: KeyboardEvent }) {
  if (event.key === "ArrowUp" || (event.key === "k" && event.ctrlKey)) {
    handleKeyUp();
    return true;
  }

  if (event.key === "ArrowDown" || (event.key === "j" && event.ctrlKey)) {
    handleKeyDown();
    return true;
  }

  if (event.key === "Enter") {
    handleKeyEnter();
    return true;
  }

  return false;
}

function handleKeyUp() {
  selectedIndex.value =
    (selectedIndex.value + props.items.length - 1) % props.items.length;
}

function handleKeyDown() {
  selectedIndex.value = (selectedIndex.value + 1) % props.items.length;
}

function handleKeyEnter() {
  handleSelectItem(selectedIndex.value);
}

function handleSelectItem(index: number) {
  const item = props.items[index];

  if (item) {
    props.command(item);
  }
}

watch(
  () => selectedIndex.value,
  () => {
    const selected = document.getElementById(
      `command-item-${selectedIndex.value}`
    );

    if (selected) {
      scrollIntoView(selected, { behavior: "smooth", scrollMode: "if-needed" });
    }
  }
);

defineExpose({
  onKeyDown,
});
</script>
<template>
  <div class="command-items">
    <template v-if="items.length">
      <div
        v-for="(item, index) in items"
        :id="`command-item-${index}`"
        :key="index"
        :class="{ 'is-selected': index === selectedIndex }"
        class="command-item"
        @click="handleSelectItem(index)"
      >
        <component :is="item.icon" class="command-icon" />
        <span class="command-title">
          {{ i18n.global.t(item.title) }}
        </span>
      </div>
    </template>
    <div v-else class="command-empty">
      <span>
        {{ i18n.global.t("editor.extensions.commands_menu.no_results") }}
      </span>
    </div>
  </div>
</template>

<style lang="scss">
.command-items {
  position: relative;
  max-height: 18rem; // max-h-72
  width: 13rem; // w-52
  overflow: hidden;
  overflow-y: auto;
  border-radius: 0.375rem; // rounded-md
  background-color: white;
  padding: 0.25rem; // p-1
  box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);

  .command-item {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 1rem; // gap-4
    border-radius: 0.25rem; // rounded
    padding: 0.25rem; // p-1

    &:hover {
      background-color: #f3f4f6; // hover:bg-gray-100

      .command-icon {
        background-color: white !important;
      }

      .command-title {
        font-weight: 500; // font-medium
        color: #111827; // text-gray-900
      }
    }

    &.is-selected {
      background-color: #f3f4f6; // bg-gray-100

      .command-icon {
        background-color: white;
      }

      .command-title {
        font-weight: 500; // font-medium
        color: #111827; // text-gray-900
      }
    }

    .command-icon {
      height: 1.5rem; // h-6
      width: 1.5rem; // w-6
      border-radius: 0.25rem; // rounded
      background-color: #f3f4f6; // bg-gray-100
      padding: 0.25rem; // p-1
    }

    .command-title {
      font-size: 0.75rem; // text-xs
      color: #4b5563; // text-gray-600
    }
  }

  .command-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0.25rem; // p-1
    font-size: 0.75rem; // text-xs
    color: #4b5563; // text-gray-600
  }
}
</style>
